<?php


namespace app\common\library;

use app\common\library\Utils;

class Iden
{
    const ZERO = 1136185445;
    const  VER = 1;

    /**
     * @param int $biz
     * @param int $version
     * @return int
     */
    static public function genID($biz, $version = self::VER)
    {
        $ms = floor(microtime(true) * 100000);
        $ts = floor($ms / 100000);
        $mask = floor($ms % 100000) % pow(2, 16);
        return self::makeID($ts, $version, $biz, $mask);
    }

    static public function uid($biz, $version = self::VER)
    {
        $ms = floor(microtime(true) * 100000);
        $ts = floor($ms / 100000);
        $mask = floor($ms % 100000) % pow(2, 16);
        return self::makeID($ts, $version, $biz, $mask);

    }

    static public function makeID($ts, $version, $biz, $mask)
    {
        // 32+8+8+8+8
        $ts -= self::ZERO;
        return ($ts << 32) | ($version << 24) | ($biz << 16) | $mask;
    }


    static public function parseID($id)
    {
        $ts = $id >> 32;
        $last = $id - ($ts << 32);
        $version = $last >> 24;
        $last = $last - ($version << 24);
        $biz = $last >> 16;
        $mask = $last - ($biz << 16);
        return [$ts + self::ZERO, $version, $biz, $mask];
    }

    static public function encrypt($id)
    {
        $bin = pack('Q', $id);
        return strrev(Utils::base64url_encode($bin));
    }

    static public function decrypt($code)
    {
        if (strlen($code) < 10) {
            return 0;
        }


        $bin = Utils::base64url_decode(strrev($code));

        $arr = unpack('Q', $bin);
        if (isset($arr[1])) {
            return $arr[1];
        }
        return 0;
    }

    static public function getBiz($code)
    {
        if (is_string($code)) {
            $id = self::decrypt($code);
            if ($id < 1000000000) {
                return 0;
            }

        } else {
            $id = $code;
        }
        list($ts, $ver, $biz, $mask) = Iden::parseID($id);
        return $biz;
    }


}